/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SRC_CPP_RTPS_TRANSPORT_UDSDGRAMTRANSPORTINTERFACE_H_
#define SRC_CPP_RTPS_TRANSPORT_UDSDGRAMTRANSPORTINTERFACE_H_

#include <deps/common/IPFinder.h>
#include <transport/TransportInterface.h>

#include <transport/UDSDgramTransportDescriptor.h>
#include <ertps/utils/LocatorAlias.h>

#include "UDSDgramChannelResource.h"

#include <thread>
#include <vector>
#include <memory>
#include <map>
#include <mutex>

#include <asio.hpp>

namespace vbs {
namespace transport {
using namespace vbsutil::xmlparser;

using Locator = vbsutil::xmlparser::Locator_t;

using SendResourceList = std::vector<std::unique_ptr<SenderResource>>;

const std::string UDSDgramMagicWord = "Send";

class UDSDgramTransportInterface : public TransportInterface {
    friend class UDSDgramSenderResource;

 public:
    UDSDgramTransportInterface(const UDSDgramTransportDescriptor& descriptor);

    ~UDSDgramTransportInterface() override;

    bool init() override;

    bool IsInputChannelOpen(const Locator&) const override;

    bool IsLocatorSupported(const Locator& locator) const override;

    bool is_locator_allowed(const Locator& locator) const override;

    bool OpenOutputChannel(SendResourceList& sender_resource_list, const Locator&) override;

    void CloseOutputChannel(asio::local::datagram_protocol::socket& socket);

    bool OpenInputChannel(const Locator& locator, std::shared_ptr<ReceiverResource>, uint32_t) override;

    bool CloseInputChannel(const Locator& locator) override;  //input-receive output-send

    bool DoInputLocatorsMatch(const Locator& left, const Locator& right) const override;

    UDSDgramTransportDescriptor* get_configuration() override { return &configuration_; }

    uint32_t max_recv_buffer_size() const override { return configuration_.max_message_size(); }

    bool send(octet* send_buffer, uint32_t send_buffer_size, asio::local::datagram_protocol::socket& socket,
              vbsutil::xmlparser::LocatorsIterator* destination_locators_begin,
              vbsutil::xmlparser::LocatorsIterator* destination_locators_end);

 protected:
    friend class UDSDgramChannelResource;

    UDSDgramTransportDescriptor configuration_;

    mutable std::recursive_mutex mInputMapMutex;

    std::map<std::string, UDSDgramChannelResource*> mInputSockets;

    uint32_t mSendBufferSize;
    uint32_t mReceiveBufferSize;

    //The actual buffer size, which is related to the system buffer
    uint32_t actual_send_buffer;
    uint32_t actual_recv_buffer;

    asio::io_context io_context_;
    bool is_bind_send_socket = false;

    asio::io_context io_context_init_;

    asio::io_context io_context_recv_;
};

}  // namespace transport
}  // namespace vbs

#endif
